home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / utils / adt / numutils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-21  |  6.4 KB  |  363 lines

  1. /*
  2.  * numutils.c --
  3.  *     utility functions for I/O of built-in numeric types.
  4.  *
  5.  *    integer:        itoa, ltoa
  6.  *    floating point:        ftoa, atof1
  7.  */
  8.  
  9. #include "tmp/postgres.h"
  10.  
  11. RcsId("$Header: /private/postgres/src/utils/adt/RCS/numutils.c,v 1.5 1991/11/09 01:52:29 mer Exp $");
  12.  
  13. #include <math.h>
  14.  
  15. int itoa ARGS((int i , char *a ));
  16. int ltoa ARGS((long l , char *a ));
  17. int ftoa ARGS((double value, char *ascii, int width, int prec1, char format ));
  18. int atof1 ARGS((char *str , double *val ));
  19.  
  20.  
  21. /*
  22.  *    itoa        - converts a short int to its string represention
  23.  *
  24.  *    Note:
  25.  *        Based on ~ingres/source/gutil/atoi.c
  26.  */
  27. itoa(i, a)
  28.     register int    i;
  29.     register char    *a;
  30. {
  31.     register char    *t;
  32.     char        temp[6];
  33.  
  34.     if (i < 0) {
  35.         i = -i;
  36.         *a++ = '-';
  37.     }
  38.     t = temp + 5;
  39.     *t-- = '\0';
  40.     do {
  41.         *t-- = i % 10 + '0';
  42.         i /= 10;
  43.     } while (i != 0);
  44.     do {
  45.         *a++ = *++t;
  46.     } while (*t != '\0');
  47. }
  48.  
  49. /*
  50.  *    ltoa        - converts a long int to its string represention
  51.  *
  52.  *    Note:
  53.  *        Based on ~ingres/source/gutil/atoi.c
  54.  */
  55. ltoa(l, a)
  56.     register long    l;
  57.     register char    *a;
  58. {
  59.     register    char    *t;
  60.     char            temp[11];
  61.  
  62.     if (l < 0) {
  63.         l = -l;
  64.         *a++ = '-';
  65.     }
  66.     t = temp + 10;
  67.     *t-- = '\0';
  68.     do {
  69.         *t-- = l % 10 + '0';
  70.         l /= 10;
  71.     } while (l != 0);
  72.     do {
  73.         *a++ = *++t;
  74.     } while (*t != '\0');
  75. }
  76.  
  77. /*
  78.  **  ftoa    - FLOATING POINT TO ASCII CONVERSION
  79.  **
  80.  **    CODE derived from ingres, ~ingres/source/gutil/ftoa.c
  81.  **
  82.  **    'Value' is converted to an ascii character string and stored
  83.  **    into 'ascii'.  Ascii should have room for at least 'width' + 1
  84.  **    characters.  'Width' is the width of the output field (max).
  85.  **    'Prec' is the number of characters to put after the decimal
  86.  **    point.  The format of the output string is controlled by
  87.  **    'format'.
  88.  **
  89.  **    'Format' can be:
  90.  **        e or E: "E" format output
  91.  **        f or F:  "F" format output
  92.  **        g or G:  "F" format output if it will fit, otherwise
  93.  **            use "E" format.
  94.  **        n or N:  same as G, but decimal points will not always
  95.  **            be aligned.
  96.  **
  97.  **    If 'format' is upper case, the "E" comes out in upper case;
  98.  **    otherwise it comes out in lower case.
  99.  **
  100.  **    When the field width is not big enough, it fills the field with
  101.  **    stars ("*****") and returns zero.  Normal return is the width
  102.  **    of the output field (sometimes shorter than 'width').
  103.  */
  104. ftoa(value, ascii, width, prec1, format)
  105.     double    value;
  106.     char    *ascii;
  107.     int    width;
  108.     int    prec1;
  109.     char    format;
  110. {
  111.     auto int    expon;
  112.     auto int    sign;
  113.     register int    avail;
  114.     register char    *a;
  115.     register char    *p;
  116.     char        mode;
  117.     int        lowercase;
  118.     int        prec;
  119.     extern char    *ecvt(), *fcvt();
  120.     
  121.     prec = prec1;
  122.     mode = format;
  123.     lowercase = 'a' - 'A';
  124.     if (mode >= 'a')
  125.         mode -= 'a' - 'A';
  126.     else
  127.         lowercase = 0;
  128.     
  129.     if (mode != 'E') {
  130.         /* try 'F' style output */
  131.         p = fcvt(value, prec, &expon, &sign);
  132.         avail = width;
  133.         a = ascii;
  134.         
  135.         /* output sign */
  136.         if (sign) {
  137.             avail--;
  138.             *a++ = '-';
  139.         }
  140.         
  141.         /* output '0' before the decimal point */
  142.         if (expon <= 0) {
  143.             *a++ = '0';
  144.             avail--;
  145.         }
  146.         
  147.         /* compute space length left after dec pt and fraction */
  148.         avail -= prec + 1;
  149.         if (mode == 'G')
  150.             avail -= 4;
  151.         
  152.         if (avail >= expon) {
  153.             
  154.             /* it fits.  output */
  155.             while (expon > 0) {
  156.                 /* output left of dp */
  157.                 expon--;
  158.                 if (*p) {
  159.                     *a++ = *p++;
  160.                 } else
  161.                     *a++ = '0';
  162.             }
  163.             
  164.             /* output fraction (right of dec pt) */
  165.             avail = expon;
  166.             goto frac_out;
  167.         }
  168.         /* won't fit; let's hope for G format */
  169.     }
  170.     
  171.     if (mode != 'F') {
  172.         /* try to do E style output */
  173.         p = ecvt(value, prec + 1, &expon, &sign);
  174.         avail = width - 5;
  175.         a = ascii;
  176.         
  177.         /* output the sign */
  178.         if (sign) {
  179.             *a++ = '-';
  180.             avail--;
  181.         }
  182.     }
  183.     
  184.     /* check for field too small */
  185.     if (mode == 'F' || avail < prec) {
  186.         /* sorry joker, you lose */
  187.         a = ascii;
  188.         for (avail = width; avail > 0; avail--)
  189.             *a++ = '*';
  190.         *a = 0;
  191.         return (0);
  192.     }
  193.     
  194.     /* it fits; output the number */
  195.     mode = 'E';
  196.     
  197.     /* output the LHS single digit */
  198.     *a++ = *p++;
  199.     expon--;
  200.     
  201.     /* output the rhs */
  202.     avail = 1;
  203.     
  204.  frac_out:
  205.     *a++ = '.';
  206.     while (prec > 0) {
  207.         prec--;
  208.         if (avail < 0) {
  209.             avail++;
  210.             *a++ = '0';
  211.         } else {
  212.             if (*p)
  213.                 *a++ = *p++;
  214.             else
  215.                 *a++ = '0';
  216.         }
  217.     }
  218.     
  219.     /* output the exponent */
  220.     if (mode == 'E') {
  221.         *a++ = 'E' + lowercase;
  222.         if (expon < 0) {
  223.             *a++ = '-';
  224.             expon = -expon;
  225.         } else
  226.             *a++ = '+';
  227.         *a++ = (expon / 10) % 10 + '0';
  228.         *a++ = expon % 10 + '0';
  229.     }
  230.     
  231.     /* output spaces on the end in G format */
  232.     if (mode == 'G') {
  233.         *a++ = ' ';
  234.         *a++ = ' ';
  235.         *a++ = ' ';
  236.         *a++ = ' ';
  237.     }
  238.     
  239.     /* finally, we can return */
  240.     *a = 0;
  241.     avail = a - ascii;
  242.     return (avail);
  243. }
  244.  
  245. /*
  246.  **   atof1    - ASCII TO FLOATING CONVERSION
  247.  **
  248.  **    CODE derived from ~ingres/source/gutil/atof.c
  249.  **
  250.  **    Converts the string 'str' to floating point and stores the
  251.  **    result into the cell pointed to by 'val'.
  252.  **
  253.  **    The syntax which it accepts is pretty much what you would
  254.  **    expect.  Basically, it is:
  255.  **        {<sp>} [+|-] {<sp>} {<digit>} [.{digit}] {<sp>} [<exp>]
  256.  **    where <exp> is "e" or "E" followed by an integer, <sp> is a
  257.  **    space character, <digit> is zero through nine, [] is zero or
  258.  **    one, and {} is zero or more.
  259.  **
  260.  **    Parameters:
  261.  **        str -- string to convert.
  262.  **        val -- pointer to place to put the result (which
  263.  **            must be type double).
  264.  **
  265.  **    Returns:
  266.  **        zero -- ok.
  267.  **        -1 -- syntax error.
  268.  **        +1 -- overflow (not implemented).
  269.  **
  270.  **    Side Effects:
  271.  **        clobbers *val.
  272.  */
  273. atof1(str, val)
  274.     char    *str;
  275.     double    *val;
  276. {
  277.     register char    *p;
  278.     double        v;
  279.     double        fact;
  280.     int        minus;
  281.     register char    c;
  282.     int        expon;
  283.     register int    gotmant;
  284.     
  285.     v = 0.0;
  286.     p = str;
  287.     minus = 0;
  288.     
  289.     /* skip leading blanks */
  290.     while (c = *p) {
  291.         if (c != ' ')
  292.             break;
  293.         p++;
  294.     }
  295.     
  296.     /* handle possible sign */
  297.     switch (c) {
  298.     case '-':
  299.         minus++;
  300.         
  301.     case '+':
  302.         p++;
  303.     }
  304.     
  305.     /* skip blanks after sign */
  306.     while (c = *p) {
  307.         if (c != ' ')
  308.             break;
  309.         p++;
  310.     }
  311.     
  312.     /* start collecting the number to the decimal point */
  313.     gotmant = 0;
  314.     for (;;) {
  315.         c = *p;
  316.         if (c < '0' || c > '9')
  317.             break;
  318.         v = v * 10.0 + (c - '0');
  319.         gotmant++;
  320.         p++;
  321.     }
  322.     
  323.     /* check for fractional part */
  324.     if (c == '.') {
  325.         fact = 1.0;
  326.         for (;;) {
  327.             c = *++p;
  328.             if (c < '0' || c > '9')
  329.                 break;
  330.             fact *= 0.1;
  331.             v += (c - '0') * fact;
  332.             gotmant++;
  333.         }
  334.     }
  335.     
  336.     /* skip blanks before possible exponent */
  337.     while (c = *p) {
  338.         if (c != ' ')
  339.             break;
  340.         p++;
  341.     }
  342.     
  343.     /* test for exponent */
  344.     if (c == 'e' || c == 'E') {
  345.         p++;
  346.         expon = atoi(p);
  347.         if (!gotmant)
  348.             v = 1.0;
  349.         fact = expon;
  350.         v *= pow(10.0, fact);
  351.     } else {
  352.         /* if no exponent, then nothing */
  353.         if (c != 0)
  354.             return (-1);
  355.     }
  356.     
  357.     /* store the result and exit */
  358.     if (minus)
  359.         v = -v;
  360.     *val = v;
  361.     return (0);
  362. }
  363.